#ifndef _NGX_POOL_HPP_
#define _NGX_POOL_HPP_

#include <iostream>
#include "cassert"
#include "NgxInclude.hpp"
#include "NgxWrapper.hpp"

class NgxPool : public NgxWrapper<ngx_pool_t>
{
public:
	using super_type 	= NgxWrapper<ngx_pool_t>;
	using this_type 	= NgxPool;
public:
	NgxPool(ngx_pool_t *p) : super_type(p) {}

	template<typename T>
	NgxPool(T* x) : super_type(x->pool) {}

	~NgxPool() = default;

public:
	template<typename T>
	T* palloc() const
	{
		auto *ptr = ngx_palloc(get(), sizeof(T));
		if (ptr == nullptr) {
			std::cout << "ngx_palloc\n"; 
			return nullptr;
		}
		assert(ptr);
		return new(ptr) T();
	}

	template<typename Func, typename T>
	ngx_pool_cleanup_t *cleanup(Func func, T *data, std::size_t size = 0) const
	{
		auto ptr = ngx_pool_cleanup_add(get(), size);
		if (ptr == nullptr) {
			std::cout << "ptr is null for ngx_palloc\n"; 
			return nullptr;
		}
		ptr->data = data;
		ptr->handler = func;

		return ptr;
	}

	template<typename T>
	void destory(void *data)
	{
		reinterpret_cast<T*>(data)->~T();
	}

	template<typename T>
	void cleanup(T *data) const
	{
		cleanup(&this_type::destory<T>, data);
	}

	template<typename T>
	void cleanup(T &data) const
	{
		cleanup(&this_type::destory<T>, &data);
	}

};



#endif // _NGX_POOL_HPP_